const { startsWith, set } = require("lodash")
const { log } = console
if (true) {
  var foo = 'user'
  let fo = 'single'
}
console.log(foo) // => 'user'
// console.log(fo) // => fo is not defined

// -----------------------------

// for(var i=0;i<3;i++){
//   console.log('外层1-'+i)
//   for(var i=0;i<3;i++){
//     console.log(i)
//   }
//   console.log('外层2-'+i)
// }
// console.log('-----------------')
// for(let i=0;i<3;i++){
//   console.log('外层1-'+i)
//   for(let i=0;i<3;i++){
//     console.log(i)
//   }
//   console.log('外层2-'+i)
// }

const obj = {}
obj.name = 'user' // 支持的
// obj={} // TypeError: Assignment to constant variable.
// 数组解构
const arr1 = ['user1', '999', '2324']
const [a1, ...res] = arr1
console.log(a1) // =>'user1'
console.log(res) // => [ '999', '2324' ]
// 对象解构
const { log } = console // console.log(),log方法是console对象的一个元素，用log同名进行匹配,简化代码
let object1 = { 'name': 'zlf', 'sex': '1', 'telephone': '111222' }
// const {telephone}= object1
// log(telephone) // => '111222'
// const {name:objName} = object1
// log(objName) // => 'zlf'
// const {name:name='2'} = object1 // object1不变
// log(object1) // => { name: 'zlf', sex: '1', telephone: '111222' }
// const {name,...obj11} = object1 // name 对的上object1中的数据，obj11获取到后面剩余的参数
// log(obj11) // => { sex: '1', telephone: '111222' }
// const {obj1,...obj12} = object1 // object1中没有obj1元素，故是undefined
// log(obj1) // => undefined
// log(obj12) // => { name: 'zlf', sex: '1', telephone: '111222' }

// 模板字符串``
// 标签前面可以添加函数
// console.log`hello world` // => [ 'hello world' ]
// let name = 'zeo'
// let age = '18'
// console.log`hi,${name}is${age}.` // => [ 'hi,', 'is', '.' ] zeo 18
// function tag(arr,name,age) {
//   console.log(arr,name,age)
// }
// tag`hi,${name}is${age}.` // => [ 'hi,', 'is', '.' ] zeo 18
// tag(`hi,${name}is${age}.`) // => hi,zeois18. undefined undefined

// 字符串的扩展方法
// const msg = 'error: name is undefined.'
// log(msg.indexOf('error')!==-1) // => true

// log(msg.startsWith('error')) // => true
// log(msg.endsWith('.')) // => true
// log(msg.includes('error')) // => true

// 参数默认值
function getThing(some, thing = '0', able = true, on) {
  log(some) // => undefined
  log(thing) // => '0'
  log(able) // => true
  log(on) // => undefined
}
// getThing()
// getThing('a','b','c') // => a b c undefined
getThing('aa') // => aa 0 true undefined

// 剩余参数
function foo2() {
  console.log(arguments)
}
foo2('1', '2', '3') // =>[Arguments] { '0': '1', '1': '2', '2': '3' } 伪数组
function foo3(...bar) {
  console.log(bar)
}
foo3('1', '2', '3') // [ '1', '2', '3' ]

// 展开数组
const arr2 = ['1', '2', '3']
// es6之前
console.log(arr2[0], arr2[1], arr2[2]) // => 1 2 3
console.log.apply(console, arr2) // => 1 2 3
// es6
console.log(...arr2) // => 1 2 3

// 箭头函数
this.name = '12221'
const preson = {
  name: 'zlf',
  getName: () => {
    log(this.name)
  },
  getName1: function () {
   log(this.name)
  },
  getNameAscyn:function () {
    name= '33333'
    setTimeout(function () {
      log('1.'+ this.name) // => 1.undefined
    }, 200);
    // setTimeout(() => {
    //   log('1.'+this.name) // =>1.zlf
    // }, 200);
  },
  
}
preson.getName() // => '12221'
preson.getName1() // => zlf
preson.getNameAscyn() // => 1.zlf

console.log('--------1---------')
for (let i = 0; i < 3; i++) {
  console.log('外层1-' + i)
  for (let i = 0; i < 3; i++) {
    console.log(i)
  }
  console.log('外层2-' + i)
}
console.log('--------2---------')
for (var j = 0; j < 3; j++) {
  let j = 'foo'
  console.log(j)
}// => 3个 foo

var array = [{}, {}, {}]
// for(var k=0;k<array.length;k++){
//   array[k].onClick = function(){
//     console.log(k) // var 定义k，k是全局变量，在循环后，k的值已经固定是3，不可变，所以永远是3
//   }
// }
// console.log(array[0].onClick()) // => 3
for (var k = 0; k < array.length; k++) {
  array[k].onClick = (function (k) { // 闭包,入参k，就是函数内局部变量，不受外面的k值影响。
    return function () {
      console.log(k)
    }
  })(k)
}
console.log(array[0].onClick())// => 0
// for(let k=0;k<array.length;k++){
//   array[k].onClick = function(){
//     console.log(k) // let 定义k，k是块级变量，每次的k值都是单独作用于循环{}之中
//   }
// }
console.log(array[0].onClick())// => 0

// const
const obj = {}
obj.name = 'user' // 支持的
// obj={} // TypeError: Assignment to constant variable.

// 数组解构
const arr1 = ['user1', '999', '2324']
const [a1, ...res] = arr1
console.log(a1) // =>'user1'
console.log(res) // => [ '999', '2324' ]
// 对象解构
// const { log } = console // console.log(),log方法是console对象的一个元素，用log同名进行匹配,简化代码
let object1 = { 'name': 'zlf', 'sex': '1', 'telephone': '111222' }
// const {telephone}= object1
// log(telephone) // => '111222'
// const {name:objName} = object1
// log(objName) // => 'zlf'
// const {name:name='2'} = object1 // object1不变
// log(object1) // => { name: 'zlf', sex: '1', telephone: '111222' }
// const {name,...obj11} = object1 // name 对的上object1中的数据，obj11获取到后面剩余的参数
// log(obj11) // => { sex: '1', telephone: '111222' }
// const {obj1,...obj12} = object1 // object1中没有obj1元素，故是undefined
// log(obj1) // => undefined
// log(obj12) // => { name: 'zlf', sex: '1', telephone: '111222' }

// 模板字符串``
// 标签前面可以添加函数
// console.log`hello world` // => [ 'hello world' ]
// let name = 'zeo'
// let age = '18'
// console.log`hi,${name}is${age}.` // => [ 'hi,', 'is', '.' ] zeo 18
// function tag(arr,name,age) {
//   console.log(arr,name,age)
// }
// tag`hi,${name}is${age}.` // => [ 'hi,', 'is', '.' ] zeo 18
// tag(`hi,${name}is${age}.`) // => hi,zeo is18. undefined undefined

// 字符串的扩展方法
// const msg = 'error: name is undefined.'
// log(msg.indexOf('error')!==-1) // => true

// log(msg.startsWith('error')) // => true
// log(msg.endsWith('.')) // => true
// log(msg.includes('error')) // => true
log('==================')
const arr0 = ['12', NaN, 'star']
log(arr0.includes(NaN))
// 参数默认值
function getThing(some, thing = '0', able = true, on) {
  log(some) // => undefined
  log(thing) // => '0'
  log(able) // => true
  log(on) // => undefined
}
// getThing()
// getThing('a','b','c') // => a b c undefined
// getThing('aa') // => aa 0 true undefined

// 剩余参数
function foo2() {
  console.log(arguments)
}
foo2('1', '2', '3') // =>[Arguments] { '0': '1', '1': '2', '2': '3' } 伪数组
function foo3(...bar) {
  console.log(bar)
}
// foo3('1', '2', '3') // [ '1', '2', '3' ]

// 展开数组
const arr2 = ['1', '2', '3']
// es6之前
// console.log(arr2[0], arr2[1], arr2[2]) // => 1 2 3
// console.log.apply(console, arr2) // => 1 2 3
// es6
// console.log(...arr2) // => 1 2 3

// 箭头函数
this.name = '12221'
const person = {
  name: 'zlf',
  getName: () => {
    log(this.name)
  },
  getName1: function () {
    log(this.name)
  },
  getNameAsync: function () {
    name = '33333'
    setTimeout(function () {
      log('1.' + this.name) // => 1.undefined
    }, 200);
    // setTimeout(() => {
    //   log('1.'+this.name) // =>1.zlf
    // }, 200);
  },

}
// person.getName() // => '12221'
// person.getName1() // => zlf
// person.getNameAsync() // => 1.zlf

// 对象字面量增强
const bar = '345'
const obj2 = {
  foo: 123,
  bar, // bar:bar
  // method1:function(){
  //   console.log(this.foo)
  // },
  method1() {
    console.log(this)
  },
  [1 + 1]: 234 // 计算属性名，用方括号包裹起来，里面可以写任意表达式
}
log(obj2.bar)
obj2.method1() // => { '2': 234, foo: 123, bar: '345', method1: [Function: method1] }

// 对象扩展方法
// Object.assign(target,source) => 返回值就是目标对象 target
const source1 = {
  a: "1",
  b: '2'
}
const target = {
  a: '3',
  c: '7'
}
const result = Object.assign(target, source1)
log(result === target) // => true 返回值就是目标对象

// Object.is()
log(Object.is(NaN, NaN)) // => true
log(NaN === NaN) // => false 建议用全等

// proxy 代理对象,vue3.0 已经广泛运用了
const person1 = {
  name: 'zlf',
  age: 10
}
let proProxy = new Proxy(person1, {
  get(target, property) { // 目标对象，要获取的属性名
    return property in target ? target[property] : 'default'
    // console.log(target,property) // proProxy.name //=> { name: 'zlf', age: '10' } name
  },
  set(target, property, value) {
    if (property === 'age') {
      if (!Number.isInteger(value)) {
        throw new TypeError(`${value} is not an int`)
      }
    }
    target[property] = value
  },
  deleteProperty(target, property) {
    delete target[property]
    // },
    // getPrototypeOf(target, property){
    //   log(target, property)
  }
})
log(proProxy) // => { name: 'zlf', age: '10' }
log(proProxy === person1) // => false 不是同一个对象，proProxy是代理对象
log(proProxy.name)// => zlf
log(proProxy.ope) // => default

// proProxy.age = '123' // => TypeError: 123 is not an int
proProxy.bar = true
log(proProxy) // => { name: 'zlf', age: 10, bar: true }

// proxy 相比于 defineProperty(只能监视对象读写)
// proxy 还能监视 delete 和 对象的方法 等
delete proProxy.age
log(proProxy) // => { name: 'zlf', bar: true }

// Object.getPrototypeOf(proProxy)


const list = []
const listProxy = new Proxy(list, {
  set(target, property, value) {
    console.log('set', property, value);
    target[property] = value;
    return true;
  }
})
listProxy.push(1000) // set 0 1000
log(list) // [1000]
